<template>
    <div class="contentChart" v-loading="isLoading" element-loading-background="rgba(0, 0, 0, 0.6)">
        <div class="box" :ref="type" @contextmenu.prevent="showMenu($event)"></div>
        <div class="label" v-show="labelShow" v-html="labelContent"></div>
        <vue-context-menu
            v-if="contextMenuData"
            :contextMenuData="contextMenuData"
            @downloadData="downloadData"
            @setMarkPoint="setMarkPoint"
            @clearPoint="clearPoint"
            @setSecondLine="setSecondLine"
            @clearLine="clearLine"
            @setFreDouCount="setFreDouCount"
            @freDoubling="freDoubling"
            @sideFre="sideFre"
            @setCharFre="setCharFre"
            @downtestfile="downtestfile"
            @setThr="setThr"
        />
        <char-fre ref="charFre" @charfre="charfre" />
        <down-data ref="downData" />
        <el-dialog width="26%" :visible.sync="multipleShow" append-to-body>
            <el-form label-width="100px" class="demo-ruleForm">
                <el-form-item label="频带数量">
                    <el-input type="number" v-model.number="number" />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="submitmultiple">确认</el-button>
                    <el-button @click="multipleShow = false">取消</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
        <el-dialog width="26%" :visible.sync="thrShow" append-to-body>
            <el-form label-width="100px" class="demo-ruleForm">
                <el-form-item v-for="item in sthCol" :key="item.name" :label="item.label">
                    <el-input type="input" v-model="sthForm[item.name]"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="submithr">确认</el-button>
                    <el-button @click="thrShow = false">取消</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
    </div>
</template>

<script>
import * as echarts from 'echarts'
import { contextMenuData, menuList, sthCol, sthForm } from '../config'
import { deepClone } from '@/plugins/clone'
import downData from '@/components/downData'
import charFre from './charFre.vue'
import { nanoid } from 'nanoid'
export default {
    data() {
        return {
            sthCol,
            sthForm,
            labelTextColor: 'white',
            isLoading: false,
            options: null,
            chart: null,
            contextMenuData: null,
            labelShow: false,
            labelContent: '',
            thrShow: false,
            refname: null,
            downDataConfig: {
                filename: '',
                data: null,
                json_fields: {},
            },
            hoverPoint: null,
            state: 1,
            // 1:默认 ，2：双游标 ,3:倍频  4 ：边频
            lines: [],
            Graphic: [],
            dragable: false,
            diffX: 0,
            multipleShow: false,
            number: 2, //频带数
            freCount: 2,
            diffIndex: null, //边频基础间隔
            baseX: null, //边频基准线坐标
            points: [],
            options: null,
        }
    },
    components: {
        downData,
        charFre,
    },
    props: {
        type: {
            type: String,
            default() {
                return ''
            },
        },
        sensorInfo: {
            type: Object,
            default() {
                return null
            },
        },
        box: {
            type: String,
            default() {
                return ''
            },
        },
    },
    methods: {
        submitmultiple() {
            if (this.number < 0) {
                this.$message('无效的频带数')
                this.number = 1
            }
            this.$message.success('频带为' + this.number)
            this.multipleShow = false
            this.freCount = this.number
        },
        submithr() {
            let arr = []
            sthCol.forEach((e, i) => {
                if (i == 0)
                    arr.push({
                        color: e.color,
                        from: 0,
                        to: Number(this.sthForm['level' + (i + 1)]),
                    })
                else
                    arr.push({
                        color: e.color,
                        from: Number(this.sthForm['level' + i]),
                        to: Number(this.sthForm['level' + (i + 1)]),
                    })
            })
            this.options.yAxis.plotBands = arr
            this.updateChart(this.options)
            this.$message.success('设置成功')
            this.thrShow = false
        },
        setTooltip(options) {
            let that = this
            var { type } = that
            options.tooltip.formatter = function () {
                const { x, y } = this
                that.hoverPoint = { x, y }
                if (type == 'eig') {
                    return '时间: ' + that.dayjs(x).format('YYYY-MM-DD HH:mm:ss') + '<br>值: ' + y
                } else if (type == 'hist') {
                    return 'volts: ' + x + '<br>个数: ' + y
                } else {
                    const tooltip = document.getElementsByClassName('charts-tooltip')[0]
                    if (tooltip) {
                        tooltip.parentNode.removeChild(tooltip)
                    }
                    return ''
                }
            }
            return options
        },
        //倍频
        freDoubling() {
            this.state = this.state == 3 ? 1 : 3
            this.markLine()
        },
        onChartClick(event) {
            let { chartX } = event
            let index = this.getIndex(chartX)
            let { xData, yData } = this.chart.series[0]
            this.lines[0] = {
                x: xData[index],
                y: yData[index],
                chartX,
                id: 'id0',
            }
            this.markLine()
            this.sendActTime()
        },
        clearLine() {
            this.clearPoint()
            this.lines = this.lines.slice(1)
            this.Graphic = []
            this.state = 1
            this.markLine()
            this.dragable = false
            this.removeLine()
        },
        onLineClick(event) {
            let { chartX } = event
            let { x, y } = event.point
            this.lines[0] = {
                x,
                y,
                chartX,
                id: 'id0',
            }
            this.sendActTime()
            this.markLine()
        },
        sendActTime() {
            if (this.type == 'trend') {
                let { x, y } = this.hoverPoint
                const item = {
                    time: this.dayjs(x).format('YYYY/MM/DD HH:mm:ss'),
                    value: y,
                }
                this.$emit('setTime', item)
            }
        },
        showMenu(e) {
            let a = this.$refs[this.type]

            let x = e.clientX
            let y = e.clientY
            this.contextMenuData.axis = { x, y }
        },
        closeMenu(e) {
            this.contextMenuData.axis = { x: -1000, y: -1000 }
        },
        setSecondLine() {
            this.state = 2
            this.lines[1] = this.lines[0]
            this.lines[1].id = 'id1'
            this.dragable = true
        },
        removeLine() {
            if (!this.chart) return
            let option = this.chart.getOption()
            if (option.series && option.series[0].markLine) {
                option.series[0].markLine.data = []
                this.chart.setOption(option)
            }
        },
        clearPoint() {
            for (var i = 0; i <= this.points.length; i++) {
                this.chart.xAxis[0].removePlotLine(`id_${i}`)
                this.chart.xAxis[0].removePlotLine(`id_${i * -1}`)
            }
            this.points.length = 0
        },
        addPlotLine(value, label, id, y) {
            if (!this.chart) return
            let option = this.chart.getOption()
            if (!option.series) return
            option.series[0].markLine = option.series[0].markLine || { data: [] }
            option.series[0].markLine.data.push({
                xAxis: value,
                label: { formatter: label },
                lineStyle: { color: 'red', type: 'dashed', width: 1.2 },
                id: id
            })
            this.chart.setOption(option)
        },
        //标记线
        markLine(drag) {
            let state = this.state
            let { xData, yData } = this.chart.series[0]
            console.log('this.options', this.options)
            let xunit = ''
            let yunit = ''
            if (this.type == 'wave') {
                xunit = this.options.xAxis.title.text
                yunit = this.options.yAxis.title.text
            }

            this.removeLine()
            //普通模式
            if (state == 1) {
                this.labelShow = false
                let { x, y, id } = this.lines[0]
                this.addPlotLine(x, `${this.isTimestamp(x) ? this.dayjs(x).format('YYYY/MM/DD HH:mm:ss') : x + xunit} , ${y.toFixed(3)}${yunit}`, id, y)
            } else if (state == 2) {
                var { x, y, chartX, id } = this.lines[0]
                let x1 = x
                let y1 = y
                this.chart.xAxis[0].removePlotLine(id)
                this.addPlotLine(x1, `${x1} , ${y1.toFixed(3)}`, id)
                var { x, y, chartX, id } = this.lines[1]
                let x2 = x
                let y2 = y
                let chartX2 = chartX
                this.chart.xAxis[0].removePlotLine(id)
                let dx = Number((x1 - x2).toFixed(3))
                let dy = Number((y1 - y2).toFixed(3))
                // this.addPlotLine(x2, `Δx:${dx}${xunit} , Δy:${dy}${yunit}`, id)
                this.addPlotLine(x2, ``, id)

                this.labelShow = true
                this.labelContent = `<div>双游标</div><div>Δx:${dx}${xunit}</div> <div>Δy:${dy}${yunit}</div>`
                // this.dragGraphic(chartX2)
            } else if (state == 3) {
                this.lines = []
                let { x } = this.hoverPoint
                let multiple = x
                let index0 = xData.indexOf(multiple)
                for (let i = 1; i <= this.freCount; i++) {
                    this.lines.push({
                        x: multiple * i,
                        y: yData[i * index0],
                        id: 'id' + i,
                    })
                }
                let con = `<div>倍频</div>`
                this.lines.forEach((e, i) => {
                    let { x, y } = e
                    console.log('e', e)
                    this.chart.xAxis[0].removePlotLine(id)
                    this.addPlotLine(x, `${this.isTimestamp(x) ? this.dayjs(x).format('HH:mm:ss') : i == 0 ? x : `${i + 1}x`}`, 'id' + i)
                    con += `<div> ${i + 1}x ：${y.toFixed(3)}${yunit}</div>`
                })
                this.labelShow = true
                this.labelContent = con
            } else if (state == 4) {
                this.lines = []
                let { x } = this.hoverPoint
                if (!drag) {
                    this.baseX = xData.indexOf(x)
                }
                if (!this.baseX) this.baseX = xData.indexOf(x)
                let dIndex = this.baseX
                if (!this.diffIndex) this.diffIndex = dIndex
                for (let i = 1; i < this.freCount; i++) {
                    let index = dIndex - i * this.diffIndex
                    if (index >= 0)
                        this.lines.unshift({
                            x: xData[index],
                            y: yData[index],
                            index: i * -1,
                            id: 'id' + i * -1,
                        })
                }
                for (let i = 0; i < this.freCount; i++) {
                    let index = i == 0 ? dIndex : dIndex + i * this.diffIndex
                    if (index >= 0)
                        this.lines.push({
                            x: xData[index],
                            y: yData[index],
                            index: i,
                            id: 'id' + i,
                        })
                }
                this.Graphic.map((e) => e.destroy())
                let con = `<div>边频</div>`
                this.lines.forEach((e, i) => {
                    let { x, y, id, index } = e
                    this.chart.xAxis[0].removePlotLine(id)
                    this.addPlotLine(x, `${this.isTimestamp(x) ? this.dayjs(x).format('HH:mm:ss') : x} , ${y.toFixed(3)}`, id)
                    con += `<div> ${i + 1}x ：${y.toFixed(3)}${yunit}</div>`
                    let pielx = this.getPiel(xData.indexOf(x))
                    this.setDrag(pielx, id)
                })
            }
        },
        setDrag(pielx, id) {
            let { xData, yData } = this.chart.series[0]
            let rectangle = this.chart.renderer
                .rect(pielx, 0, 8, 1000, 5)
                .attr({
                    fill: '#083DCE', // 设置填充颜色为白色
                    'fill-opacity': 0, // 设置填充透明度为 0，即完全透明
                    zIndex: 5,
                    cursor: 'col-resize',
                    id,
                })
                .add()
            let startX, startY, startXPos, startYPos
            rectangle.on('mousedown', function (event) {
                startX = event.clientX
                startY = event.clientY
                startXPos = rectangle.attr('x')
                startYPos = rectangle.attr('y')
                event.preventDefault()
                event.stopPropagation()
                if (ondragstart) {
                    ondragstart()
                }
            })
            let that = this
            document.addEventListener('mouseup', function (event) {
                if (that.dragable)
                    if (startX !== undefined && startY !== undefined && startXPos !== undefined && startYPos !== undefined) {
                        let currentX = event.clientX
                        let currentY = event.clientY
                        let diffX = currentX - startX
                        let diffY = currentY - startY
                        let newXPos = startXPos + diffX
                        let newYPos = startYPos + diffY
                        rectangle.attr({ x: newXPos, y: 0 })
                        that.lines.forEach((e, i) => {
                            if (e.id == id) {
                                if (i > that.lines.length / 2) {
                                    let a1 = xData.indexOf(that.lines[i - 1].x)
                                    let a2 = that.getIndex(newXPos)
                                    that.diffIndex = a2 - a1
                                } else if (i < that.lines.length / 2) {
                                    let a1 = xData.indexOf(that.lines[i + 1].x)
                                    let a2 = that.getIndex(newXPos)
                                    that.diffIndex = a2 - a1
                                }
                            }
                        })
                        that.markLine()
                    }
                startX = undefined
                startY = undefined
                startXPos = undefined
                startYPos = undefined
            })
            this.Graphic.push(rectangle)
        },
        // 导出
        downloadData() {
            const { type } = this.options.xAxis
            const { series } = this.options
            if (series.length == 1) {
                let { data } = series[0]
                this.downDataConfig.filename = this.sensorInfo.sensor_name
                let data1 = []
                if (type == 'datetime')
                    data.forEach((element) => {
                        data1.push({
                            x: this.dayjs(element[0]).format('YYYY-MM-DD HH:mm:ss'),
                            y: element[1],
                        })
                    })
                else
                    data.forEach((element) => {
                        data1.push({
                            x: element[0],
                            y: element[1],
                        })
                    })
                this.downDataConfig.data = data1
                this.downDataConfig.json_fields = {
                    x: 'x',
                    y: 'y',
                }
                this.$refs.downData.downloadData(this.downDataConfig)
            }
        },
        setCharFre() {
            this.$refs.charFre.open(this.sensorInfo.device_id)
        },
        initChart(options) {
            this.options = options
            if (this.type == 'fre') options.xAxis.tickInterval = 100
            else if (this.type == 'wave') options.xAxis.tickInterval = 100
            this.clearChart()
            this.chart = echarts.init(this.$refs[this.type])
            this.chart.setOption(this.convertToEchartsOption(options))
            this.isLoading = false
            this.chart.on('click', this.onChartClick)
        },
        dragGraphic(x) {
            if (x < 0) x = 0
            this.Graphic.map((e) => e.destroy())
            let rectangle = this.chart.renderer
                .rect(x, 0, 10, 1000, 3)
                .attr({
                    fill: '#083DCE',
                    'fill-opacity': 0, // 设置填充透明度为 0.1
                    zIndex: 5,
                    cursor: ' col-resize',
                    id: 'drag-rectangle',
                })
                .add()
            let startX, startY, startXPos, startYPos
            rectangle.on('mousedown', function (event) {
                startX = event.clientX
                startY = event.clientY
                startXPos = rectangle.attr('x')
                startYPos = rectangle.attr('y')
                event.preventDefault()
                event.stopPropagation()
                if (ondragstart) {
                    ondragstart()
                }
            })
            let that = this
            document.addEventListener('mousemove', function (event) {
                if (startX !== undefined && startY !== undefined && startXPos !== undefined && startYPos !== undefined) {
                    let currentX = event.clientX
                    let currentY = event.clientY
                    let diffX = currentX - startX
                    let diffY = currentY - startY
                    let newXPos = startXPos + diffX
                    let newYPos = startYPos + diffY
                    rectangle.attr({ x: newXPos, y: newYPos })
                    if (ondrag) ondrag()
                }
            })
            document.addEventListener('mouseup', function (event) {
                if (that.dragable)
                    if (startX !== undefined && startY !== undefined && startXPos !== undefined && startYPos !== undefined) {
                        let currentX = event.clientX
                        let currentY = event.clientY
                        let diffX = currentX - startX
                        let diffY = currentY - startY
                        let newXPos = startXPos + diffX
                        let newYPos = startYPos + diffY
                        rectangle.attr({ x: newXPos, y: 0 })
                        let { x, y } = that.hoverPoint
                        // newXPos 拖拽后的像素坐标
                        that.lines[1] = { x, y, chartX: newXPos }
                        that.markLine()
                    }
                startX = undefined
                startY = undefined
                startXPos = undefined
                startYPos = undefined
            })
            this.Graphic.push(rectangle)
        },
        updateChart(options) {
            this.$nextTick(() => {
                options = this.setTooltip(options)
                this.options = options
                if (this.chart) {
                    this.clearChart()
                }
                this.initChart(options)
                // this.isLoading = false
                this.contextMenuData.menulists = menuList[this.type]
            })
        },
        charfre(list) {
            this.points = list
            this.points.forEach((l, i) => {
                let { x, y } = l
                this.chart.xAxis[0].addPlotLine({
                    value: x,
                    color: 'red',
                    dashStyle: 'LongDash',
                    width: 1.2,
                    id: 'id' + i,
                    label: {
                        text: `${y}:${x.toFixed(2)}`,
                        align: 'center',
                        x: -40,
                        style: {
                            color: this.labelTextColor,
                        },
                        rotation: -30,
                    },
                    zIndex: 999,
                })
                const renderer = this.chart.renderer
            })
        },
        startLoading() {
            this.isLoading = true
        },
        isTimestamp(timestamp) {
            const regex = /^\d{13}$/
            return regex.test(timestamp)
        },
        clearChart() {
            if (this.chart) {
                this.chart.dispose()
                this.chart = null
            }
        },
        setMarkPoint() {
            this.points.push(this.hoverPoint)
            this.points.forEach((e, i) => {
                let { x, y } = e
                this.addPlotLine(x, `${this.isTimestamp(x) ? this.dayjs(x).format('HH:mm:ss') : x} , ${y.toFixed(3)}`, 'id_' + i)
                const renderer = this.chart.renderer
            })
        },
        setFreDouCount() {
            this.multipleShow = true
        },
        // 边频
        sideFre() {
            if (this.state != 4) this.state = 4
            else this.state = 1
            this.dragable = !this.dragable
            this.markLine()
        },
        //根据索引获取像素坐标
        getPiel(index) {
            let xAxis = this.chart.xAxis[0]
            let series = this.chart.series[0] // 假设这里是第一个系列
            let point = series.points[index] // 获取指定索引处的数据点
            let xValue = point.x // 获取数据点的 x 值
            let xPixel = xAxis.toPixels(xValue) // 将 x 值转换为像素坐标
            return xPixel
        },
        //根据像素坐标获取索引
        getIndex(xPixel) {
            let xAxis = this.chart.xAxis[0]
            let xValue = xAxis.toValue(xPixel) // 将像素坐标转换为 x 轴上的值
            // 找到最接近的数据点的索引坐标
            let series = this.chart.series[0] // 假设这里是第一个系列
            let closestPoint = series.data.reduce((prev, curr) => {
                return Math.abs(curr.x - xValue) < Math.abs(prev.x - xValue) ? curr : prev
            })
            let index = closestPoint.index // 获取最接近数据点的索引坐标
            return index
        },
        extractStrings(a) {
            // 提取 '端' 前两个字符并加上 '端'，得到字符串 b
            const index = a.indexOf('端')
            let b = ''
            if (index !== -1) {
                b = a.substring(index - 2, index) + '端'
            }
            // 提取字符串 b前面的所有字符，组成字符串 c
            let c = ''
            if (index !== -1) {
                c = a.substring(0, index - 2)
            }
            return [b, c]
        },
        downtestfile() {
            let { direction, address, port, sensor_name, device_id } = this.sensorInfo
            let { freq, series, time, wave_type } = this.options
            let { data } = series[0]
            let dir = {
                V: '垂直',
                A: '轴向',
                H: '水平',
            }
            let rmsdata = 3000
            let len = data.length
            let precision = 24
            let arr = this.extractStrings(sensor_name)
            let { unit } = wave_type
            let filename = '样本数据' + port + address + this.dayjs().second()
            let textData = [
                port + address + this.dayjs().second(),
                arr[1],
                arr[0],
                dir[direction] + direction,
                rmsdata,
                time,
                freq,
                len,
                precision, //第九行数据的采样精度
                unit,
                JSON.stringify(data.map((e) => Number(e[1].toFixed(3)))),
                '------end-----',
            ]
            this.downloadTxtFile(textData, filename)
        },
        downloadTxtFile(textData, filename) {
            this.$message.success('正在下载')
            // 将数据转换为文本格式
            const textContent = textData.join('\n')
            // 创建一个新 Blob 对象，并指定数据类型为"text/plain"
            const blob = new Blob([textContent], { type: 'text/plain' })

            // 创建一个链接元素
            const a = document.createElement('a')
            a.href = window.URL.createObjectURL(blob)
            a.download = filename
            // 模拟点击链接以下载文件
            a.click()
            // this.$message.success("下载完成")
        },
        setThr() {
            this.thrShow = true
        },
        convertToEchartsOption(options) {
            // 复制原始 options，避免污染
            let xAxis = { ...(options.xAxis || {}) }
            let yAxis = { ...(options.yAxis || {}) }

            if (xAxis.type === 'datetime') xAxis.type = 'time'
            if (xAxis.type === 'linear') xAxis.type = 'value'
            if (yAxis.type === 'datetime') yAxis.type = 'time'
            if (yAxis.type === 'linear') yAxis.type = 'value'

            let echartsOption = {
                title: options.title || {},
                tooltip: {
                    trigger: 'axis',
                    formatter: options.tooltip && options.tooltip.formatter ? options.tooltip.formatter : undefined
                },
                legend: options.legend || {},
                xAxis,
                yAxis,
                series: options.series || []
            }
            return echartsOption
        },
    },
    created() {
        // 绑定图表的菜单
        this.contextMenuData = deepClone(contextMenuData)
        this.contextMenuData.menulists = menuList[this.type]
        this.contextMenuData.menuName = this.type + nanoid()
    },
    beforeDestroy() {
        if (this.chart) this.chart.destroy()
    },
}
</script>

<style lang="less" scoped>
.contentChart {
    width: 100%;
    height: 100%;

    position: relative;
    .box {
        height: 100% !important;

        width: 100%;
        left: 0;
        position: absolute;
    }
    .label {
        font-size: 12px;
        position: absolute;
        width: 100px;
        z-index: 99;
        background-color: #04204c;
        border: 1px solid #1961cc;
        border-radius: 4px;
        right: 0;
        color: white;
        top: 0;
        div {
            text-align: center;
            width: 100%;
            height: 10px;
        }
    }
}
</style>
